package com.platform.qujia.utils.weixinapp;


import cn.hutool.core.thread.ThreadUtil;
import com.platform.qujia.constantEnum.RedisKey;
import com.platform.qujia.enums.WxTemplateEnum;
import com.platform.qujia.pojo.Enterprise;
import com.platform.qujia.pojo.WxMessageTemplate;
import com.platform.qujia.pojo.wx.WxAccessTokenRes;
import com.platform.qujia.pojo.wx.WxTemplateMessageSendRequest;
import com.platform.qujia.service.EnterpriseService;
import com.platform.qujia.service.WxMessageTemplateService;
import com.platform.qujia.service.WxTemplateParamsGeneral;
import com.platform.qujia.task.BatchTaskExecutor;
import com.platform.qujia.utils.HttpClientUtil;
import com.platform.qujia.utils.exception.CustomException;
import com.platform.qujia.utils.redis.RedisCacheUtil;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/***
 * <Title>  WxPushUtil  </Title>
 * <Description> 微信公众号消息推送 </Description>
 * @author JK
 * @date 2021年2月19日
 */
@Component
public class WxPushUtil {
    private static final Logger logger = LoggerFactory.getLogger(WxPushUtil.class);

    private final Object tokenLock = new Object();

    @Autowired
    private Map<String, WxTemplateParamsGeneral> wxTemplateParamsGeneralMap;

    @Autowired
    private WxMessageTemplateService wxMessageTemplateService;

    @Autowired
    private EnterpriseService enterpriseService;

    ThreadPoolExecutor threadPoolExecutor = ThreadUtil.newExecutor(10, 20);

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Value("${qujia.bgBaseUrl}")
    private String bgBaseUrl;

    /*
     * 微信推送新修订版： 2022年2月9日12:25:44
     * @param appId
     * @param appSecret
     * @param wxTemplateMsg
     * @return
     * @throws WxErrorException
     */
    public void sendTemplateMsg(String appId, String appSecret, WxTemplateMsg wxTemplateMsg) {
        try {
            String tokenCache = getGzhTokenFromCache(appId,appSecret);
            if (StringUtils.isEmpty(tokenCache)) {
                logger.info("消息推送失败，token获取失败");
                return;
            }
//            synchronized (this) {
//                String accessTokenKey = "access_token_" + appId;
//                if (!redisCacheUtil.hasKey(accessTokenKey) || redisCacheUtil.getCacheObject(accessTokenKey) == null) {
////                    String token =HttpRequestUtil.getAcccessTokenHttpsRequestData(tokenHttp,"post","{"+appId+"}");
////                    String token =HttpRequestUtil.getAcccessTokenHttpsRequestData(tokenHttp,"get","\""+appId+"\"");
////                    String token =HttpRequestUtil.getAcccessTokenHttpsRequestData(tokenHttp.replace("gzhAppId",appId),"get","");
//                    String mmm = tokenHttp.replace("gzhAppId", appId);
//                    String token = HttpRequestUtil.getAcccessTokenHttpsRequestData(mmm, "GET", null);
////                    if(token!=null&&token.length()<150){
////                        token = WeiXinUserUtil.getToken(appId, appSecret).getAccessToken();
////                    }
//                    token = WeiXinUserUtil.getToken(appId, appSecret).getAccessToken();
//
//                    // String token = WeiXinUserUtil.getToken(appId, appSecret).getAccessToken();
//                    redisCacheUtil.setCacheObject(accessTokenKey, token);
//                    redisCacheUtil.expire(accessTokenKey, 7100, TimeUnit.SECONDS);
//                    tokenCache = token;
//                } else {
//                    tokenCache = redisCacheUtil.getCacheObject(accessTokenKey);
//                }
//            }
            //logger.info(">sendTemplateMsg-access_token:" + tokenCache);
            String send_url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + tokenCache;
            //JSONObject jsonObject = HttpClientUtil.doPostJson(send_url, com.alibaba.fastjson.JSONObject.toJSONString(wxTemplateMsg));
            ResponseEntity<String> response = restTemplate.postForEntity(send_url, wxTemplateMsg, String.class, (Object) null);
            String body = response.getBody();
            if (body == null) {
                logger.error(">pushfinish-消息推送失败原因:返回body为空");
                return;
            }
            logger.info(">pushfinish-消息推送成功返回:" + body);
        } catch (Exception e) {
            logger.error(">pushfinish-消息推送失败原因:", e);
        }
    }

    public void sendTemplateMsg(Integer enterpriseId, Map<String, String> templateParams, WxTemplateEnum wxTemplateEnum) {
        threadPoolExecutor.execute(()->{
            Enterprise enterprise = enterpriseService.selectEnterpriseInfo(enterpriseId);
            if (ObjectUtils.isEmpty(enterprise)) return;
            //if (StringUtils.isEmpty(enterprise.getGzhAppId()) || StringUtils.isEmpty(enterprise.getGzhAppSecret())) return;
            if(StringUtils.isEmpty(enterprise.getGzhAppId())){
                return ;
            }else{
                try {
//                    synchronized (this) {
//                        String accessTokenKey = "access_token_" + enterprise.getGzhAppId();
//                        if (!redisCacheUtil.hasKey(accessTokenKey) || redisCacheUtil.getCacheObject(accessTokenKey) == null) {
//                            String mmm = tokenHttp.replace("gzhAppId", enterprise.getGzhAppId());
//                            String token = HttpRequestUtil.getAcccessTokenHttpsRequestData(mmm, "GET", null);
//                            token = WeiXinUserUtil.getToken(enterprise.getGzhAppId(), enterprise.getGzhAppSecret()).getAccessToken();
//
//                            redisCacheUtil.setCacheObject(accessTokenKey, token);
//                            redisCacheUtil.expire(accessTokenKey, 6000, TimeUnit.SECONDS);
//                            tokenCache = token;
//                        } else {
//                            tokenCache = redisCacheUtil.getCacheObject(accessTokenKey);
//                        }
//                    }
                    String wxTemplateParams = getWxTemplateParams(enterpriseId, templateParams, wxTemplateEnum);
                    logger.info("公众号推送消息请求："+wxTemplateParams);
                    //JSONObject jsonObject = HttpClientUtil.doPostJson(send_url, wxTemplateParams);
                    String body = sendWxTemplateMsg(enterprise.getGzhAppId(),enterprise.getGzhAppSecret(),wxTemplateParams);
                    if (body == null) {
                        logger.error("消息推送失败原因:返回body为空");
                        return;
                    }
                    logger.info("微信模板消息推送结果：jsonObject:{}", body);
                } catch (Exception e) {
                    logger.error(">pushfinish-消息推送失败原因:", e);
                }
            }
        });
    }

    public String sendWxTemplateMsg(String appId,String appSecret,String reqBody){
        String accessToken = getGzhTokenFromCache(appId, appSecret);
        if (StringUtils.isEmpty(accessToken)) {
            logger.info("消息推送失败，token获取失败");
            return null;
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.put(HttpHeaders.CONTENT_TYPE, Collections.singletonList(MediaType.APPLICATION_JSON_UTF8_VALUE));
        HttpEntity<String> httpEntity = new HttpEntity<>(reqBody,httpHeaders);
        ResponseEntity<String> response = restTemplate.postForEntity("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken, httpEntity, String.class, (Object) null);
        return response.getBody();
    }

    public Token getGzhTokenFromWx(String appId, String appSecret){
        Token token = null;
        if (StringUtils.isBlank(appSecret)){
            String to = restTemplate.getForObject(bgBaseUrl + "/thirdParty/weChat/getAccessToken?authorizerAppid="+appId,String.class);
            if(StringUtils.isEmpty(to) || to.contains("\"code\":500")){
                logger.error("调用第三方平台token失败，appId:[{}],msg:{}",appId,to);
                return token;
            }
            token = new Token();
            token.setAccessToken(to);
            token.setExpiresIn(7200);
        }else {
            String requestUrl = WeiXinUserUtil.token_url.replace("APPID", appId).replace("APPSECRET", appSecret);
            //发起GET请求获取凭证
            WxAccessTokenRes tokenRes = restTemplate.getForObject(requestUrl, WxAccessTokenRes.class, (Object) null);
            if (tokenRes != null && tokenRes.getErrcode()==0) {
                token = new Token();
                token.setAccessToken(tokenRes.getAccessToken());
                token.setExpiresIn(tokenRes.getExpiresIn());
            }
        }
        return token;
    }

    public String getGzhTokenFromCache(String appId, String appSecret){
        String redisKey = RedisKey.GZH_APPID_TOKEN + appId;
        String accessToken = redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isBlank(accessToken)) {
            synchronized (tokenLock){
                accessToken = redisTemplate.opsForValue().get(redisKey);
                if (StringUtils.isBlank(accessToken)) {
                    Token token = this.getGzhTokenFromWx(appId, appSecret);
                    if (token == null || StringUtils.isBlank(token.getAccessToken())) {
                        return null;
                    }
                    accessToken = "\""+token.getAccessToken()+"\""; // 之前代码token保存的时候进行了json转换，所以开头结尾加上了双引号，为了兼容别的代码在这里加上
                    redisTemplate.opsForValue().set(redisKey, accessToken, 6000, TimeUnit.SECONDS);
                }
            }
        }
        // 返回去掉双引号
        return accessToken.substring(1, accessToken.length() - 1);
    }

    private String getWxTemplateParams(Integer enterpriseId, Map<String, String> templateParams, WxTemplateEnum wxTemplateEnum) {
        WxMessageTemplate wxMessageTemplate = wxMessageTemplateService.getByEnterpriseIdAndType(Long.valueOf(enterpriseId), wxTemplateEnum.getCode());
        if (ObjectUtils.isEmpty(wxMessageTemplate)) throw new CustomException("该油企未配置对应模板");
        if (ObjectUtils.isEmpty(templateParams.get("openid"))) throw new CustomException("openid为空");

        HashMap<String, Object> params = new HashMap<>();
        params.put("touser", templateParams.get("openid"));
        params.put("template_id", wxMessageTemplate.getTemplateId());
        // 跳转链接
        if (StringUtils.isNotEmpty(wxMessageTemplate.getTemplateUrl())) {
            params.put("url", wxMessageTemplate.getTemplateUrl());
        }
        // 标题
        HashMap<String, Map<String, String>> data = new HashMap<>();
        if (StringUtils.isNotEmpty(wxMessageTemplate.getTemplateName())) {
            HashMap<String, String> dataFirst = new HashMap<>();
            dataFirst.put("value", wxMessageTemplate.getTemplateName());
            data.put("first", dataFirst);
        }
        // 备注
        if (StringUtils.isNotEmpty(wxMessageTemplate.getTemplateRemark())) {
            HashMap<String, String> remark = new HashMap<>();
            remark.put("value", wxMessageTemplate.getTemplateRemark());
            remark.put("color", "#000000");
            data.put("remark", remark);
        }

        // 设置其他模板内容
        if (StringUtils.isNotEmpty(wxMessageTemplate.getTemplateContent())) {
            List<String> contents = Arrays.asList(wxMessageTemplate.getTemplateContent().split(","));
            wxTemplateParamsGeneralMap.get(wxTemplateEnum.getType()).setWxTemplateContent(contents, templateParams, data);
        }
        params.put("data", data);
        return com.alibaba.fastjson.JSONObject.toJSONString(params);
    }
}
